#include "user_adc.h"

/*****ADC读取模式切换*****/
// 1 - 轮询模式
// 2 - DMA+定时处理
// 3 - 定时器触发+DMA+块处理
#define ADC_MODE 2 //ADC读取模式宏定义

/************************ADC读取实现******************************/

#if ADC_MODE == 1  //轮询读取adc模式

uint32_t adc_val;//adc获取值
/**
 * @brief 单通道轮询获取adc值
 * @param *hadc
 * @return volatage
 */
float adc_read_by_polling(ADC_HandleTypeDef *hadc)
{
    //启动adc转换
    HAL_ADC_Start(hadc);
    //等待转换完成
    if(HAL_ADC_PollForConversion(hadc,1000) == HAL_OK)
    {
        //获取adc转换值
        adc_val = HAL_ADC_GetValue(hadc);
        //adc值转换为实际电压值
        float volatage = (float)adc_val*3.3f/4095.0f;
        //调试信息
        user_printf(&huart1,"{POLLING} ADC value:%lu, Volatage:%f\r\n",adc_val,volatage);
			

        return volatage;
    }
    else
    {
        //转换超时或出错
        user_printf(&huart1,"ADC TimeOut\r\n");
    }
}
/**
 * @brief adc任务函数
 * @param none
 * @return none
 */
void adc_task(void)
{
    adc_read_by_polling(&hadc1);
}

#elif ADC_MODE == 2  //DMA搬运+定时处理

uint32_t adc_dma_buffer[ADC_DMA_BUFFER_SIZE];//dma数据接收缓冲区(adc)
uint32_t adc_val;//用于存储adc平均值
float volatage;//存储转换后的电压值
float v_get;
/**
 * @brief adc dma初始化
 * @param none
 * @return none
 */
void adc_dma_init(void)
{
    HAL_ADC_Start_DMA(&hadc1,adc_dma_buffer,ADC_DMA_BUFFER_SIZE);
}
/**
 * @brief adc任务函数
 * @param none
 * @return none
 */
void adc_task(void)
{
    uint32_t adc_sum = 0;
    for(uint16_t i = 0;i<ADC_DMA_BUFFER_SIZE;i++)
    {
        //累加
        adc_sum += adc_dma_buffer[i];
    }
    //取平均值,获取当前adc数据
    adc_val = adc_sum/ADC_DMA_BUFFER_SIZE;
    //将读取到的值转换为电压值
    v_get = (float)adc_val * 3.3f / 4095.0f;

    //调试信息
    //user_printf(&huart1,"{DMA} ADC value:%lu, Volatage:%.2f\r\n",adc_val,volatage);
}

#elif ADC_MODE == 3 //ADC精准采样 定时器触发+DMA+块处理

uint32_t adc_dma_buffer[ADC_DMA_BUFFER_SIZE];//dma数据缓存区
uint32_t adc_read_buffer[ADC_DMA_BUFFER_SIZE/2];//adc数据处理缓冲区
uint8_t adc_convend;//dma搬运完成标志位
/**
 * @brief ADC精准采样 定时器+DMA初始化
 * @param none
 * @return none
 */
void adc_tim_dma_init(void)
{
    //开启dma通道
    HAL_ADC_Start_DMA(&hadc1,adc_dma_buffer,ADC_DMA_BUFFER_SIZE);
    //关闭DMA半满中断
    __HAL_DMA_DISABLE_IT(&hdma_adc1,DMA_IT_HT);
    //开启定时器
    HAL_TIM_Base_Start(&htim3);
}
/**
 * @brief adc转换完成回调函数
 * @param hadc 
 * @return none
 */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
    //检查是否由目标ADC触发
    if(hadc->Instance == ADC1)
    {
        //停止dma搬运
        HAL_ADC_Stop_DMA(hadc);
        //拉高完成标志位，通知cpu已经完成
        adc_convend = 1;
    }
}
/**
 * @brief adc任务函数
 * @param none
 * @return none
 */
void adc_task(void)
{
    //如果dma搬运完成,进行数据处理
    if(adc_convend == 1)
    {
        for(uint16_t i = 0;i<ADC_DMA_BUFFER_SIZE/2;i++)
        {
            adc_read_buffer[i] = adc_dma_buffer[i*2 + 1];
            float volatage = (float)adc_read_buffer[i] * 3.3f/4095.0f;
            user_printf(&huart1,"{tim} adc_value:%lu,volatage:%.2f\r\n",adc_read_buffer[i],volatage);
        }
        //数据处理缓冲区清空
        memset(adc_read_buffer,0,sizeof(uint32_t) * ADC_DMA_BUFFER_SIZE/2);
        //清空dma搬运标志位
        adc_convend = 0;
        //重新开启dma通道
        HAL_ADC_Start_DMA(&hadc1,adc_dma_buffer,ADC_DMA_BUFFER_SIZE);
        //关闭DMA半满中断
        __HAL_DMA_DISABLE_IT(&hdma_adc1,DMA_IT_HT);
    }
}
#endif
